package com.halfsword.creativecraft.recipe;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.halfsword.creativecraft.CreativeCraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;

import java.util.HashMap;
import java.util.Map;

public class SpaceCollectorRecipe extends BaseMachineRecipe {

    // ================= 特有属性 =================
    private final boolean isShapeless;
    private final int maxHeight;
    private final int minHeight;
    private final ResourceLocation dimension;
    private final Map<ResourceLocation, ItemStack> dimensionOutputs;

    public SpaceCollectorRecipe(boolean isShapeless,
                                NonNullList<Ingredient> inputs,
                                ItemStack output,
                                ResourceLocation id,
                                String group,
                                int maxHeight,
                                int minHeight,
                                ResourceLocation dimension,
                                int processingTime,
                                Map<ResourceLocation, ItemStack> dimensionOutputs) {
        super(id, group, inputs, output, processingTime);
        this.isShapeless = isShapeless;
        this.maxHeight = maxHeight;
        this.minHeight = minHeight;
        this.dimension = dimension;
        this.dimensionOutputs = dimensionOutputs != null ?
                new HashMap<>(dimensionOutputs) : new HashMap<>();
    }

    // ================= 核心方法 =================
    public ItemStack getOutputForDimension(Level level, BlockPos pos) {
        if (level == null) {
            CreativeCraft.LOGGER.warn("尝试获取维度输出时 level 为 null");
            return null;
        }

        ResourceLocation currentDim = level.dimension().location();

        // 1. 优先检查维度特定输出
        if (!dimensionOutputs.isEmpty() && dimensionOutputs.containsKey(currentDim)) {
            ItemStack output = dimensionOutputs.get(currentDim);
            if (output != null && !output.isEmpty()) {
                return output.copy();
            }
        }

        // 2. 检查配方维度要求
        if (dimension != null) {
            if (dimension.equals(currentDim)) {
                return this.output.copy();
            } else {
                CreativeCraft.LOGGER.debug("维度不匹配: 需要 {}, 实际 {}",
                        dimension, currentDim);
                return null;
            }
        }

        // 3. 无维度要求时返回默认输出
        return this.output.copy();
    }

    // ================= 配方匹配逻辑 =================
    @Override
    public boolean matches(Container container, Level level) {
        // 检查高度限制
        if (level != null) {
            BlockPos pos = container instanceof PositionalContainer
                    ? ((PositionalContainer) container).getPosition()
                    : BlockPos.ZERO;

            if (pos.getY() < minHeight || pos.getY() > maxHeight) {
                CreativeCraft.LOGGER.debug("高度 {} 超出范围 [{}, {}]",
                        pos.getY(), minHeight, maxHeight);
                return false;
            }
        }

        // 根据配方类型选择匹配方式
        boolean matchResult = isShapeless ?
                matchesShapeless(container) :
                matchesShaped(container);

        CreativeCraft.LOGGER.debug("配方 {} 匹配结果: {}", id, matchResult);
        return matchResult;
    }

    /**
     * 有序配方匹配（严格槽位顺序）
     */
    private boolean matchesShaped(Container container) {
        // 确保容器有足够槽位
        int containerSize = container.getContainerSize();
        int requiredSlots = inputs.size();

        if (containerSize < requiredSlots) {
            CreativeCraft.LOGGER.warn("容器槽位不足: 需要 {}，实际 {}",
                    requiredSlots, containerSize);
            return false;
        }

        for (int i = 0; i < requiredSlots; i++) {
            Ingredient ingredient = inputs.get(i);
            ItemStack stackInSlot = container.getItem(i);

            if (!ingredient.test(stackInSlot)) {
                CreativeCraft.LOGGER.debug("槽位 {} 不匹配: 需要 {}，实际 {}",
                        i, ingredient, stackInSlot);
                return false;
            }
        }

        // 检查额外槽位是否为空（如果需要）
        if (containerSize > requiredSlots) {
            for (int i = requiredSlots; i < containerSize; i++) {
                if (!container.getItem(i).isEmpty()) {
                    CreativeCraft.LOGGER.debug("额外槽位 {} 非空", i);
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 无序配方匹配（总量匹配）
     */
    private boolean matchesShapeless(Container container) {
        // 1. 统计所有输入槽的物品（按类型分组）
        Map<ResourceLocation, Integer> availableCounts = new HashMap<>();
        for (int i = 0; i < container.getContainerSize(); i++) {
            ItemStack stack = container.getItem(i);
            if (!stack.isEmpty()) {
                ResourceLocation itemId = BuiltInRegistries.ITEM.getKey(stack.getItem());
                availableCounts.merge(itemId, stack.getCount(), Integer::sum);
            }
        }

        // 2. 统计配方需要的物品数量
        Map<ResourceLocation, Integer> requiredCounts = new HashMap<>();
        for (Ingredient ingredient : inputs) {
            boolean ingredientMatched = false;
            for (ItemStack matchingStack : ingredient.getItems()) {
                if (!matchingStack.isEmpty()) {
                    ResourceLocation itemId = BuiltInRegistries.ITEM.getKey(matchingStack.getItem());
                    requiredCounts.merge(itemId, 1, Integer::sum);
                    ingredientMatched = true;
                    break;
                }
            }
            if (!ingredientMatched) {
                CreativeCraft.LOGGER.error("配方 {} 包含无效的原料", id);
                return false;
            }
        }

        // 3. 检查物品数量是否满足
        for (Map.Entry<ResourceLocation, Integer> entry : requiredCounts.entrySet()) {
            ResourceLocation itemId = entry.getKey();
            int required = entry.getValue();
            int available = availableCounts.getOrDefault(itemId, 0);
            if (available < required) {
                CreativeCraft.LOGGER.debug("物品 {} 不足: 需要 {}, 实际 {}",
                        itemId, required, available);
                return false;
            }
        }

        return true;
    }

    // ================= 特有方法 =================
    public boolean isShapeless() {
        return isShapeless;
    }

    public int getMaxHeight() {
        return maxHeight;
    }

    public int getMinHeight() {
        return minHeight;
    }

    public ResourceLocation getDimension() {
        return dimension;
    }

    public Map<ResourceLocation, ItemStack> getDimensionOutputs() {
        return new HashMap<>(dimensionOutputs);
    }

    // ================= 实现抽象方法 =================
    @Override
    public RecipeSerializer<?> getSerializer() {
        return Serializer.INSTANCE;
    }

    @Override
    public RecipeType<?> getType() {
        return Type.INSTANCE;
    }

    // ================= 配方序列化器 =================
    public static class Serializer implements RecipeSerializer<SpaceCollectorRecipe> {
        public static final Serializer INSTANCE = new Serializer();
        public static final ResourceLocation ID =
                ResourceLocation.fromNamespaceAndPath(CreativeCraft.MOD_ID, "unified_space_collector");

        @Override
        public SpaceCollectorRecipe fromJson(ResourceLocation recipeId, JsonObject json) {
            // 1. 解析配方类型
            boolean shapeless = GsonHelper.getAsBoolean(json, "shapeless", false);

            // 2. 解析输出物品
            JsonObject outputObj = GsonHelper.getAsJsonObject(json, "output");
            ItemStack output = ShapedRecipe.itemStackFromJson(outputObj);

            // 3. 解析输入原料
            JsonArray ingredients = GsonHelper.getAsJsonArray(json, "ingredients");
            NonNullList<Ingredient> inputs = NonNullList.create();

            for (JsonElement element : ingredients) {
                Ingredient ingredient = Ingredient.fromJson(element, false);
                if (ingredient.isEmpty()) {
                    CreativeCraft.LOGGER.warn("配方 {} 包含空原料", recipeId);
                }
                inputs.add(ingredient);
            }

            // 4. 解析分组
            String group = GsonHelper.getAsString(json, "group", "");

            // 5. 解析高度限制
            int minHeight = GsonHelper.getAsInt(json, "min_height", -64);
            int maxHeight = GsonHelper.getAsInt(json, "max_height", 320);

            // 6. 解析维度要求
            ResourceLocation dimension = null;
            if (json.has("dimension")) {
                String dimStr = GsonHelper.getAsString(json, "dimension");
                if (!dimStr.isEmpty()) {
                    dimension = ResourceLocation.tryParse(dimStr);
                }
            }

            // 7. 解析处理时间
            int processingTime = GsonHelper.getAsInt(json, "processing_time", 200);

            // 8. 解析维度输出映射
            Map<ResourceLocation, ItemStack> dimOutputs = new HashMap<>();
            if (json.has("dimension_outputs")) {
                JsonObject outputsObj = GsonHelper.getAsJsonObject(json, "dimension_outputs");
                for (Map.Entry<String, JsonElement> entry : outputsObj.entrySet()) {
                    String dimKey = entry.getKey();
                    JsonElement outputElem = entry.getValue();

                    ResourceLocation dimId = ResourceLocation.tryParse(dimKey);
                    if (dimId == null) {
                        CreativeCraft.LOGGER.error("无效的维度ID: {}", dimKey);
                        continue;
                    }

                    ItemStack stack;
                    if (outputElem.isJsonObject()) {
                        stack = ShapedRecipe.itemStackFromJson(outputElem.getAsJsonObject());
                    } else if (outputElem.isJsonPrimitive()) {
                        String itemId = outputElem.getAsString();
                        Item item = BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(itemId));
                        if (item == null || item == Items.AIR) {
                            CreativeCraft.LOGGER.error("无效的物品ID: {}", itemId);
                            continue;
                        }
                        stack = new ItemStack(item);
                    } else {
                        CreativeCraft.LOGGER.error("无效的输出格式: {}", outputElem);
                        continue;
                    }

                    if (stack.isEmpty()) {
                        CreativeCraft.LOGGER.warn("维度 {} 输出为空", dimId);
                        continue;
                    }

                    dimOutputs.put(dimId, stack);
                }
            }

            return new SpaceCollectorRecipe(shapeless, inputs, output, recipeId, group,
                    maxHeight, minHeight, dimension, processingTime, dimOutputs);
        }

        @Override
        public SpaceCollectorRecipe fromNetwork(ResourceLocation recipeId, FriendlyByteBuf buffer) {
            // 1. 读取配方类型
            boolean shapeless = buffer.readBoolean();

            // 2. 读取原料数量
            int ingredientCount = buffer.readVarInt();
            NonNullList<Ingredient> inputs = NonNullList.withSize(ingredientCount, Ingredient.EMPTY);
            for (int i = 0; i < ingredientCount; i++) {
                inputs.set(i, Ingredient.fromNetwork(buffer));
            }

            // 3. 读取输出物品
            ItemStack output = buffer.readItem();

            // 4. 读取分组
            String group = buffer.readUtf();

            // 5. 读取高度和维度
            int minHeight = buffer.readInt();
            int maxHeight = buffer.readInt();

            ResourceLocation dimension = null;
            if (buffer.readBoolean()) {
                dimension = buffer.readResourceLocation();
            }

            // 6. 读取处理时间
            int processingTime = buffer.readVarInt();

            // 7. 读取维度输出映射
            int mapSize = buffer.readVarInt();
            Map<ResourceLocation, ItemStack> dimOutputs = new HashMap<>(mapSize);
            for (int i = 0; i < mapSize; i++) {
                ResourceLocation dimId = buffer.readResourceLocation();
                ItemStack stack = buffer.readItem();
                dimOutputs.put(dimId, stack);
            }

            return new SpaceCollectorRecipe(shapeless, inputs, output, recipeId, group,
                    maxHeight, minHeight, dimension, processingTime, dimOutputs);
        }

        @Override
        public void toNetwork(FriendlyByteBuf buffer, SpaceCollectorRecipe recipe) {
            // 1. 写入配方类型
            buffer.writeBoolean(recipe.isShapeless);

            // 2. 写入原料数量
            buffer.writeVarInt(recipe.inputs.size());

            // 3. 写入所有原料
            for (Ingredient ingredient : recipe.inputs) {
                ingredient.toNetwork(buffer);
            }

            // 4. 写入输出物品
            buffer.writeItem(recipe.output);

            // 5. 写入分组
            buffer.writeUtf(recipe.getGroup());

            // 6. 写入高度和维度
            buffer.writeInt(recipe.minHeight);
            buffer.writeInt(recipe.maxHeight);

            // 写入维度（如果有）
            buffer.writeBoolean(recipe.dimension != null);
            if (recipe.dimension != null) {
                buffer.writeResourceLocation(recipe.dimension);
            }

            // 7. 写入处理时间
            buffer.writeVarInt(recipe.processingTime);

            // 8. 写入维度输出映射
            buffer.writeVarInt(recipe.dimensionOutputs.size());
            for (Map.Entry<ResourceLocation, ItemStack> entry : recipe.dimensionOutputs.entrySet()) {
                buffer.writeResourceLocation(entry.getKey());
                buffer.writeItem(entry.getValue());
            }
        }
    }

    // ================= 位置感知容器接口 =================
    public interface PositionalContainer {
        BlockPos getPosition();
    }

    // ================= 配方类型 =================
    public static class Type implements RecipeType<SpaceCollectorRecipe> {
        public static final Type INSTANCE = new Type();
        public static final String ID = "unified_space_collector";
    }
}